//
//  main.cpp
//  OpenGLDemo1
//
//  Created by HFY on 2018/5/30.
//  Copyright © 2018年 Demo. All rights reserved.
//

// System Headers
#include <glad/glad.h>
#include <GLFW/glfw3.h>

// Standard Headers
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <math.h>

#include "Demo1.hpp"
#include "Demo2.hpp"

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 800;

Demo1 *demo1;
Demo2 *demo2;
bool isMouseDown = false;
double lastX, lastY;
double pitch = 0, yaw = -90;


void processInput(GLFWwindow *window);
void framebuffer_size_callback(GLFWwindow* window, int width, int height); // 回调函数原型声明
void mouse_scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void mouse_callback(GLFWwindow *window, double xpos, double ypos);
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);

void showEnvironmentVariables() {
    int maxVertexAttributes, maxTextureImageUnits;
    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttributes);
    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, & maxTextureImageUnits);
    std::cout << "Maximum nr of vertext attributes supported: " << maxVertexAttributes << std::endl;
    std::cout << "Max texture image units: " << maxTextureImageUnits << std::endl;
}

int main(int argc, char * argv[]) {
    // 初始化GLFW
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
    // 创建一个窗口对象
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "OpenGL Beginner", NULL, NULL);
    if (window == NULL) {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return EXIT_FAILURE;
    }
    // 通知GLFW将我们窗口的上下文设置为当前线程的主上下文了
    glfwMakeContextCurrent(window);
    // 对窗口注册一个回调函数,每当窗口改变大小，GLFW会调用这个函数并填充相应的参数供你处理
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    glfwSetScrollCallback(window, mouse_scroll_callback);
    glfwSetCursorPosCallback(window, mouse_callback);
    glfwSetMouseButtonCallback(window, mouse_button_callback);
    // 初始化GLAD用来管理OpenGL的函数指针
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return EXIT_FAILURE;
    }
    
//    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
    
    // 配置绘制环境和绑定数据
    showEnvironmentVariables();
    
    demo1 = new Demo1();
    demo2 = new Demo2();
    
    // 渲染循环
    while (!glfwWindowShouldClose(window)) {
        // 输入
        processInput(window);
        
        // 渲染指令
//        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // 绘制
//        demo1->draw();
        demo2->draw();
        
        // 检查并调用事件，交换缓冲
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    
    // 释放/删除之前的分配的所有资源
    glfwTerminate();
    return EXIT_SUCCESS;
}

//输入控制，检查用户是否按下了返回键(Esc)
void processInput(GLFWwindow *window) {
    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
        glfwSetWindowShouldClose(window, true);
    }
    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
        demo2->moveForward();
    } else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
        demo2->moveBack();
    } else if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
        demo2->moveLeft();
    } else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
        demo2->moveRight();
    }
}

// 滚轮事件
void mouse_scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
    // 通过鼠标滚轮控制左右移动
//    if (yoffset == 0) {
//        if (xoffset < 0) {
//            demo2 -> moveRight();
//        } else {
//            demo2 -> moveLeft();
//        }
//    } else {
//        if (yoffset < 0) {
//            demo2 -> moveForward();
//        } else {
//            demo2 -> moveBack();
//        }
//    }
    
    // 通过鼠标滚轮控制放大缩小
    demo2 -> zoomWith(yoffset);
}

// 鼠标移动事件
void mouse_callback(GLFWwindow *window, double xpos, double ypos) {
    if (isMouseDown) {
        double xoffset = xpos - lastX;
        double yoffset = lastY - ypos;
        lastX = xpos;
        lastY = ypos;
        double sensitivity = 0.05;
        xoffset *= sensitivity;
        yoffset *= sensitivity;
        
        yaw -= xoffset;
        pitch -= yoffset;
        
        if (pitch > 89.0f) {
            pitch = 89.0f;
        }
        if (pitch < -89.0f) {
            pitch = -89.0f;
        }
        demo2 -> update((float)pitch, (float)yaw);
    }
}

// 鼠标点击、释放事件
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
    if (action == GLFW_PRESS) {
        isMouseDown = true;
        glfwGetCursorPos(window, &lastX, &lastY);
        std::cout << "mouse press" << std::endl;
    } else if (action == GLFW_RELEASE) {
        isMouseDown = false;
        std::cout << "mouse release" << std::endl;
    }
}

// 当用户改变窗口的大小的时候，视口也应该被调整
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
    // 注意：对于视网膜(Retina)显示屏，width和height都会明显比原输入值更高一点。
    glViewport(0, 0, width, height);
}

